package com.cicadasmall.system.controller;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.cicadasmall.common.resp.R;
import com.cicadasmall.common.utils.SecurityUtils;
import com.cicadasmall.security.LoginUserDetails;
import com.cicadasmall.system.service.ITokenService;
import com.cicadasmall.system.vo.TokenVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;

import java.util.HashMap;
import java.util.Map;
import java.util.stream.Collectors;

@Api(tags = "G-Oauth2认证接口")
@Slf4j
@RestController
public class OAuthController {

    @Autowired
    private ITokenService tokenService;

    @Autowired
    private AuthenticationManager authenticationManager;


    @ApiOperation(value = "密码模式获取令牌")
    @PostMapping(value = "/oauth/token")
    public OAuth2AccessToken passwordToken(
            @ApiParam(name = HttpHeaders.AUTHORIZATION, value = "请求头", required = true)
            @RequestHeader(HttpHeaders.AUTHORIZATION) String header,
            @ApiParam(name = "grant_type", value = "授权类型:password")
            @RequestParam(value = "grant_type", defaultValue = "password") String grantType,
            @ApiParam(name = "username", value = "帐号", required = true)
            @RequestParam(value = "username") String username,
            @ApiParam(name = "password", value = "密码", required = true)
            @RequestParam(value = "password") String password
    ) {
        return tokenService.passwordToken(header, grantType, username, password);
    }

    @ApiOperation(value = "手机号获取令牌")
    @PostMapping(value = "/oauth/mobile/token")
    public OAuth2AccessToken mobileToken(
            @ApiParam(name = HttpHeaders.AUTHORIZATION, value = "请求头", required = true)
            @RequestHeader(HttpHeaders.AUTHORIZATION) String header,
            @ApiParam(name = "grant_type", value = "授权类型:mobile")
            @RequestParam(value = "grant_type", defaultValue = "mobile") String grantType,
            @ApiParam(name = "deviceId", value = "设备Id", required = true)
            @RequestParam(value = "deviceId") String deviceId,
            @ApiParam(name = "mobile", value = "手机号", required = true)
            @RequestParam(value = "mobile") String mobile,
            @ApiParam(name = "smsCode", value = "短信验证码", required = true)
            @RequestParam(value = "smsCode") String code
    ) {
        return tokenService.mobileToken(header, grantType, deviceId, mobile, code);
    }

    @ApiOperation(value = "微信小程序Code获取令牌")
    @PostMapping(value = "/oauth/wxma/token")
    public OAuth2AccessToken wxMaToken(
            @ApiParam(name = HttpHeaders.AUTHORIZATION, value = "请求头", required = true)
            @RequestHeader(HttpHeaders.AUTHORIZATION) String header,
            @ApiParam(name = "grant_type", value = "授权类型:wxma")
            @RequestParam(value = "grant_type", defaultValue = "wxma") String grantType,
            @ApiParam(name = "js_code", value = "微信jsCode", required = true)
            @RequestParam(value = "js_code") String code
    ) {
        return tokenService.wxMaToken(header, grantType, code);
    }

    @ApiOperation(value = "微信授权码code获取令牌")
    @PostMapping(value = "/oauth/wxmp/token")
    public OAuth2AccessToken wxMpToken(
            @ApiParam(name = HttpHeaders.AUTHORIZATION, value = "请求头", required = true)
            @RequestHeader(HttpHeaders.AUTHORIZATION) String header,
            @ApiParam(name = "grant_type", value = "授权类型:wxmp")
            @RequestParam(value = "grant_type", defaultValue = "wxmp") String grantType,
            @ApiParam(name = "code", value = "code", required = true)
            @RequestParam(value = "code") String code
    ) {
        return tokenService.wxMpToken(header, grantType, code);
    }

    @ApiOperation(value = "授权码模式获取令牌")
    @GetMapping(value = "/oauth/code/token")
    public OAuth2AccessToken authorizationCodeToken(
            @ApiParam(name = "client_id", value = "应用id", required = true)
            @RequestParam(value = "client_id") String clientId,
            @ApiParam(name = "client_secret", value = "应用密钥", required = true)
            @RequestParam(value = "client_secret") String clientSecret,
            @ApiParam(name = "code", value = "授权码", required = true)
            @RequestParam(value = "code") String code,
            @ApiParam(name = "grant_type", value = "授权类型:authorization_code")
            @RequestParam(value = "grant_type", defaultValue = "authorization_code") String grantType,
            @ApiParam(name = "redirect_uri", value = "回调地址")
            @RequestParam(value = "redirect_uri") String redirectUri
    ) {
        return tokenService.authorizationCodeToken(clientId, clientSecret, code, grantType, redirectUri);
    }


    @ApiOperation(value = "客户端模式获取令牌")
    @PostMapping(value = "/oauth/client/token")
    public OAuth2AccessToken clientTokenInfo(@ApiParam(name = HttpHeaders.AUTHORIZATION, value = "客户信息", required = true)
                                             @RequestHeader(HttpHeaders.AUTHORIZATION) String header) {

        return tokenService.clientToken(header);

    }

    @ApiOperation(value = "刷新令牌")
    @PostMapping(value = "/oauth/token/refresh")
    public OAuth2AccessToken refreshToken(
            @ApiParam(name = "token", value = "令牌", required = true)
            @RequestParam(value = "token") String token) {

        return tokenService.refreshToken(token);
    }

    @ApiOperation(value = "获取令牌信息")
    @GetMapping(value = "/oauth/token/read")
    public OAuth2AccessToken getTokenInfo(
            @ApiParam(name = "token", value = "令牌", required = true)
            @RequestParam(value = "token") String token) {

        return tokenService.getTokenInfo(token);

    }

    @ApiOperation(value = "获取用户信息")
    @PostMapping(value = "/oauth/userinfo")
    public R getUserInfo() {
        Map<String, Object> userInfo = new HashMap<>();
        LoginUserDetails loginUserDetails = (LoginUserDetails) SecurityUtils.getCurrentLoginUser();
        loginUserDetails.setPassword(null);
        userInfo.put("user", loginUserDetails);
        userInfo.put("roles", loginUserDetails.getAuthorities().stream().filter(e -> e.getAuthority().startsWith("ROLE_")).map(GrantedAuthority::getAuthority).collect(Collectors.toList()));
        return R.ok(userInfo);
    }

    @ApiOperation(value = "令牌列表")
    @GetMapping(value = "/oauth/token/list")
    public R<Page<TokenVO>> tokenList(
            @ApiParam(value = "页码", required = true)
            @RequestParam(value = "current", defaultValue = "1") Integer current,
            @ApiParam(value = "数量", required = true)
            @RequestParam(value = "size", defaultValue = "10") Integer size) {
        return R.ok(tokenService.getTokenList(current, size));
    }

    @ApiOperation(value = "移除令牌")
    @PostMapping(value = "/oauth/token/remove")
    public R<String> removeToken(
            @ApiParam(value = "令牌", required = true)
            @RequestParam(value = "token") String token) {
        return R.ok(tokenService.removeToken(token));
    }

    @ApiOperation(value = "登陆视图")
    @GetMapping("/account/signIn")
    public ModelAndView login() {
        return new ModelAndView("login");
    }

}
